package main

/*
* Content: 具名函数、匿名函数、函数做参数与返回值、defer延迟执行
* --------------------------------------------------
* Go 函数详解 func 匿名函数 闭包: https://juejin.cn/post/7073279289101123614
* golang 匿名函数func(){}() 最后括号是干啥的: https://blog.csdn.net/qq_38374562/article/details/124087021
 */

import "fmt"

func MyFunction() {

	// 具名函数
	fmt.Println("--------------------具名函数--------------------")

	// 有返回值的函数 (无命名返回值)
	res := add(2, 3)
	fmt.Printf("add(2, 3): %v\n", res)

	// 有返回值的函数 (命名返回值)
	res2 := add2(4, 5)
	fmt.Printf("add(4, 5): %v\n", res2)

	// 多个返回值
	res3, res4 := 819, 610
	res3, res4 = change(res3, res4)
	fmt.Printf("change(819, 610): %v, %v\n", res3, res4)

	// 无返回值的函数
	hello()

	// 可变长参数
	// 可变长参数必须放在函数参数的最后
	fun1("谢清照", 8, 1, 9)

	// 匿名函数
	fmt.Println("--------------------匿名函数--------------------")

	// 普通匿名函数
	var add5 = func(a, b int) int {
		return a + b
	}
	res5 := add5(3, 4)
	fmt.Printf("add2(3, 4): %v\n", res5)

	// 声明后立即调用法 ( 开启协程 等需要用到这种方式)
	func(n int) {
		fmt.Printf("声明后立即调用的匿名函数, 传入的参数是: %v\n", n)
	}(10)

	// 函数做参数与返回值
	fmt.Println("--------------------函数做参数与返回值--------------------")
	// 暂不了解

	// 延迟函数测试(defer)
	fmt.Println("--------------------defer延迟执行--------------------")
	deferDemo()

}

// 有返回值的函数 (无命名返回值)
func add(a, b int) int {
	return a + b
}

// 有返回值的函数 (命名返回值)
func add2(a, b int) (res int) {
	res = a + b
	return
}

// 多个返回值
func change(a, b int) (int, int) {
	a, b = b, a
	return a, b
}

// 无返回值的函数
func hello() {
	fmt.Println("Hello World!")
}

// 可变长参数
// 可变长参数必须放在函数参数的最后
func fun1(x string, y ...int) {
	fmt.Println(x)
	fmt.Println(y)
}

// 函数作为函数参数的类型
func f3(x func() int) {
	ret := x()
	fmt.Printf("f3打印ret的值：%v\n", ret)  //2
	fmt.Printf("f3打印ret的类型：%T\n", ret) //int
}

func ff(x, y int) int {
	return x + y
}

// 函数不仅可以作为参数，还可以作为返回值
func f5(x func() int) func(int, int) int {
	return ff
}

// defer 延迟执行
func deferDemo() {
	defer fmt.Println("111") //最先defer的语句最后执行
	defer fmt.Println("222")
	fmt.Println("333")
}
